package chloroform

import _root_.util.logging.Logged
import _root_.util.StreamUtils
import javax.servlet.http.{HttpServletRequest, HttpServletResponse, HttpServlet}
import json.ConfigSessionHandlerImp
import l10n.ProjectLocale
import util.{JsonRendererUtil, RequestUtils}
import java.io.{OutputStream, InputStreamReader}
import javax.servlet.{ServletConfig, ServletException}
import argo.jdom.{JsonRootNode, JsonNodeBuilder, JsonNode, JsonObjectNodeBuilder}

/**
 * Created by IntelliJ IDEA.
 * User: zslajchrt
 * Date: 24.2.11
 * Time: 16:38
 * To change this template use File | Settings | File Templates.
 */

class ProjectServlet extends HttpServlet with Logged {

  override def doGet(req: HttpServletRequest, resp: HttpServletResponse) = {
    handleRequest(req, resp)
  }

  override def doPost(req: HttpServletRequest, resp: HttpServletResponse) = {
    handleRequest(req, resp)
  }

  var isMetaProject: Boolean = false;

  override def init(config: ServletConfig) = {
    super.init(config)
    val isMetaProjectParam: String = config.getInitParameter("isMetaProject")
    isMetaProject = isMetaProjectParam != null && isMetaProjectParam == "true"
  }

  def getProjectResource(req: HttpServletRequest): Resource = {
    val app: ConfigPageRegisterLookup = ConfigPageRegisterLookup.get(req.getSession)
    val resolver = app.getResourceResolver
    resolver.resolve(getProjectName(app)  + ".json")
  }

  def getProjectName(app: ConfigPageRegisterLookup): String = {
    if (isMetaProject)
      app.getMetaProjectName
    else
      app.getProjectName
  }

  def getProject(app: ConfigPageRegisterLookup): Project with ProjectLocale = {
    if (isMetaProject)
      app.getMetaProjectRef.getProject
    else
      app.getProjectRef.getProject
  }

  def renderJsonNode(resp: HttpServletResponse, entriesBuilder: JsonNodeBuilder[JsonRootNode]): Unit = {
    resp.setContentType("text/plain")
    resp.setCharacterEncoding("utf-8")
    val writer = resp.getWriter
    JsonRendererUtil.makeRenderer(entriesBuilder).render(writer)
    writer.flush
  }

  def handleRequest(req: HttpServletRequest, resp: HttpServletResponse) = {
    if (req.getPathInfo.endsWith("dump")) {
      var resource = getProjectResource(req)

      val out = resp.getOutputStream
      StreamUtils.copy(resource.openInputStream, out)
      resp.setContentType("application/json")
      resp.setCharacterEncoding("utf-8")
      out.flush

    } else if (req.getPathInfo.endsWith("store")) {
      var resource = getProjectResource(req)

      val outputStream: OutputStream = resource.openOutputStream
      StreamUtils.copy(req.getInputStream, outputStream)
      outputStream.close

      // reload the project
      val app: ConfigPageRegisterLookup = ConfigPageRegisterLookup.get(req.getSession)
      val projectCache = app.getProjectCache
      if (projectCache != null) {
        projectCache.reloadProject(getProjectName(app))
      }

    } else if (req.getPathInfo.endsWith("ext")) {
      val app: ConfigPageRegisterLookup = ConfigPageRegisterLookup.get(req.getSession)
      val project = getProject(app)
      val extPath = req.getParameter("extPath")
      var entry: ProjectEntry = project.findInPath(extPath)

//      val pathSteps = extPath.split(",")
//      val rootStep = pathSteps.head
//      val extSteps = pathSteps.tail
//
//      var rootEntry: ProjectEntry = project.getEntry(pathSteps(0))
//      extSteps.foreach(extStep => {
//        rootEntry.extensions.find(_.name == extStep) match {
//          case None => error("extension " + extStep + " not found")
//          case Some(ext) => {
//            rootEntry = ext
//          }
//        }
//      })

      val entriesBuilder: JsonNodeBuilder[JsonRootNode] =
        ConfigSessionHandlerImp.getSelectedProjectEntriesBuilder(project, entry.extensions.asInstanceOf[List[TypedProjectEntry]])
      renderJsonNode(resp, entriesBuilder)

    } else {
      val app: ConfigPageRegisterLookup = ConfigPageRegisterLookup.get(req.getSession)
      val project = getProject(app)
      val scenario = req.getParameter("scenario")

      debug("Beginning building JSON model for project")
      val ts = System.currentTimeMillis
      val entriesBuilder: JsonNodeBuilder[JsonRootNode] = ConfigSessionHandlerImp.getProjectEntriesBuilder(project, scenario)
      debug("Building JSON model for project: " + (System.currentTimeMillis - ts) / 1000)

      renderJsonNode(resp, entriesBuilder)
    }

  }

}